// The whole system
export class MySystem{
    constructor(){
        this.mySystemMemoryManager = null;
        this.mySystemProcessModule = null;
        this.mySystemFileModule = null;
        this.mySystemDeviceManager = null;
    }
}

// The memory management.
export class MySystemMemoryManager {
    constructor(memSize) {
        this.mem_size = memSize;
        this.mem_map = []; //  Array of Type MyPage
        if (memSize) {
            for (let i = 0;i<memSize;i++){
                this.mem_map.push(new MyPage(i));
            }
        }
    }
}

// The process schedule module of system.
export class MySystemProcessModule{
    constructor(){

    }
}

// The file management module of system.
export class MySystemFileModule {
    constructor(){
        this.openFiles = [];
    }
    open(absPath){}
    close(f_id){}
    read(f_id, block_index){}
    write(f_id, block_index, data){}
}

// The device management module of system.
export class MySystemDeviceManager {
    constructor(){
        this.myDeviceDisk = null;
    }
}

// The device disk.
export class MyDeviceDisk {
    constructor(myMBR){
        this.MBR = myMBR;
        this.partitions = [];
    }
    addPartition(myPartition){
        this.partitions.push(myPartition);
    }
    write(index, data){
        for (let i = 0;i<this.partitions.length;i++){
            let partition = this.partitions[i];
            if (partition instanceof MyPartition && partition.begin_block <= index && index < partition.begin_block + partition.total_size){
                partition.blocks[index - partition.begin_block] = data;
                break;
            }
        }
    }
}

// On behalf of a block on disk.
export class Block {
    constructor(){
        this.available = true;
        this.block_data = null;
    }
    setData(newData){
        this.block_data = newData;
    }
    getData(){
        return this.block_data;
    }
}

// The MBR on the disk.
export class MyMBR {
    constructor(){
        this.mbr = [];
        this.dpt = [];
    }
    pushDptItem(myMBRDptItem){
        this.dpt.push(myMBRDptItem);
    }
}

// The item in mbr dpt.
export class MyMBRDptItem {
    constructor(state, type, begin, size){
        this.state = state;
        this.type = type;
        this.begin = begin;
        this.size = size;
    }
}

// A partition on the disk
export class MyPartition {
    constructor(p_name, p_type, begin, size){
        this.p_name = p_name;
        this.p_type = p_type;
        this.begin_block = begin;
        this.total_size = size;
        this.blocks = [];
        for (let i = 0;i< size;i++){
            this.blocks.push(new Block());
        }
    }
}

// BitMap
export class MyBitMap {
    constructor(num){
        this.available = [];
        this.num = num;
        for (let i = 0;i<num;i++){
            this.available.push(true);
        }
    }
    init(beginArray){
        if (beginArray instanceof Array){
            for (let i = 0;i< beginArray.length; i++){
                this.available[i] = beginArray[i];
            }
        }
    }
    free(index){
        this.available[index] = true;
    }
    use(index){
        this.available[index] = false;
    }
    getAvailableIndex(){
        for (let i = 0;i<this.num;i++){
            if (this.available[i] === true) {
                return i;
            }
        }
    }
}

// PCB
export class MyPCB {
    constructor(){
        this.p_id = null;
        this.nice = 0;
        this.comm = "";
        this.start_time = null;
        this.fd_array = [];
        this.mmap = [];
        this.pgd = [];
    }
}

// VMA
export class MyVMArea {
    constructor(){
        this.vm_task = null;
        this.vm_start = 0;
        this.vm_end = 0;
        this.vm_inode = null;
    }
}

// INode
export class MyINode {
    constructor(){
        this.i_inode = 0;
        this.i_count = 0;
        this.i_mode = null;
        this.i_atime = null;
        this.i_mtime = null;
        this.i_ctime = null;
        this.i_blocks = 0;
        this.i_bytes = 0;
        // the index info, 10 for direct, 1 plus, 1 plus, 1 plus.
        this.i_index = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
    }
}

// Page
export class MyPage {
    constructor(location){
        this.location = location;
        this.mapping = null;
        this.i_index = null;
        this.page_data = null;
    }
    setData(newData){
        this.page_data = newData;
    }
    getData(){
        return this.page_data;
    }
}
